/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
 * 
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 */
//
// CConn
//
// Methods on CConn are called from both the GUI thread and the thread which
// processes incoming RFB messages ("the RFB thread").  This means we need to
// be careful with synchronization here.
//
// Any access to writer() must not only be synchronized, but we must also make
// sure that the connection is in RFBSTATE_NORMAL.  We are guaranteed this for
// any code called after serverInit() has been called.  Since the DesktopWindow
// isn't created until then, any methods called only from DesktopWindow can
// assume that we are in RFBSTATE_NORMAL.


package vnc.server.rfb.messages;

import java.awt.Event;
/**
 * Just a snippet to restore key/mouse events back.
 * @author mar
 *
 */
public class CConn {
  ////////////////////////////////////////////////////////////////////
  // The following methods are all called from the RFB thread

  // writeClientCutText() is called from the clipboard dialog
  synchronized public void writeClientCutText(String str) {
    _writeClientCutText(str);
  }

  private void _writeClientCutText(String str) {
//	    startMsg(MsgTypes.clientCutText);
//	    os.pad(3);
//	    os.writeString(str);
//	    endMsg();
  }

  private void _writePointerEvent(int x, int y, int buttonMask2) {
//	  startMsg(MsgTypes.pointerEvent);
//	    os.writeU8(buttonMask);
//	    os.writeU16(x);
//	    os.writeU16(y);
//	    endMsg();
  }

private void _writeKeyEvent(int keysym, boolean down) {
//    startMsg(MsgTypes.keyEvent);
//    os.writeU8(down?1:0);
//    os.pad(2);
//    os.writeU32(key);
//    endMsg();
   }

synchronized public void writeKeyEvent(int keysym, boolean down) {
    _writeKeyEvent(keysym, down);
  }

  synchronized public void writeKeyEvent(Event ev) {
    if (ev.id != Event.KEY_PRESS && ev.id != Event.KEY_ACTION)
      return;

    final int keysym;

    if (ev.id == Event.KEY_PRESS) {
      if (ev.key < 32) {
        // if the ctrl modifier key is down, send the equivalent ASCII since we
        // will send the ctrl modifier anyway

        if ((ev.modifiers & Event.CTRL_MASK) != 0) {
          if ( ev.key + 96 == 127 ){
        	  keysym = 95;
          } else {
        	  keysym = ev.key + 96;
          }
        } else {
          switch (ev.key) {
          case Event.BACK_SPACE: keysym = Keysyms.BackSpace; break;
          case Event.TAB:        keysym = Keysyms.Tab; break;
          case Event.ENTER:      keysym = Keysyms.Return; break;
          case Event.ESCAPE:     keysym = Keysyms.Escape; break;
          default: return;
          }
        }

      } else if (ev.key == 127) {
        keysym = Keysyms.Delete;

      } else {
        keysym = UnicodeToKeysym.translate(ev.key);
        if (keysym == -1)
          return;
      }

    } else {
      // KEY_ACTION

      switch (ev.key) {
      case Event.HOME:         keysym = Keysyms.Home; break;
      case Event.END:          keysym = Keysyms.End; break;
      case Event.PGUP:         keysym = Keysyms.Page_Up; break;
      case Event.PGDN:         keysym = Keysyms.Page_Down; break;
      case Event.UP:           keysym = Keysyms.Up; break;
      case Event.DOWN:         keysym = Keysyms.Down; break;
      case Event.LEFT:         keysym = Keysyms.Left; break;
      case Event.RIGHT:        keysym = Keysyms.Right; break;
      case Event.F1:           keysym = Keysyms.F1; break;
      case Event.F2:           keysym = Keysyms.F2; break;
      case Event.F3:           keysym = Keysyms.F3; break;
      case Event.F4:           keysym = Keysyms.F4; break;
      case Event.F5:           keysym = Keysyms.F5; break;
      case Event.F6:           keysym = Keysyms.F6; break;
      case Event.F7:           keysym = Keysyms.F7; break;
      case Event.F8:           keysym = Keysyms.F8; break;
      case Event.F9:           keysym = Keysyms.F9; break;
      case Event.F10:          keysym = Keysyms.F10; break;
      case Event.F11:          keysym = Keysyms.F11; break;
      case Event.F12:          keysym = Keysyms.F12; break;
      case Event.PRINT_SCREEN: keysym = Keysyms.Print; break;
      case Event.PAUSE:        keysym = Keysyms.Pause; break;
      case Event.INSERT:       keysym = Keysyms.Insert; break;
      default: return;
      }
    }

    writeModifiers(ev.modifiers);
    writeKeyEvent(keysym, true);
    writeKeyEvent(keysym, false);
    writeModifiers(0);
  }


  synchronized public void writePointerEvent(Event ev) {
    switch (ev.id) {
    case Event.MOUSE_DOWN:
      buttonMask = 1;
      if ((ev.modifiers & Event.ALT_MASK) != 0) buttonMask = 2;
      if ((ev.modifiers & Event.META_MASK) != 0) buttonMask = 4;
      break;
    case Event.MOUSE_UP:
      buttonMask = 0;
      break;
    }

    writeModifiers(ev.modifiers & ~Event.ALT_MASK & ~Event.META_MASK);

//    if (ev.x < 0) ev.x = 0;
//    if (ev.x > cp.width-1) ev.x = cp.width-1;
//    if (ev.y < 0) ev.y = 0;
//    if (ev.y > cp.height-1) ev.y = cp.height-1;

    _writePointerEvent(ev.x, ev.y, buttonMask);

    if (buttonMask == 0) writeModifiers(0);
  }


  void writeModifiers(int m) {
    if ((m & Event.SHIFT_MASK) != (pressedModifiers & Event.SHIFT_MASK))
      writeKeyEvent(Keysyms.Shift_L, (m & Event.SHIFT_MASK) != 0);
    if ((m & Event.CTRL_MASK) != (pressedModifiers & Event.CTRL_MASK))
      writeKeyEvent(Keysyms.Control_L, (m & Event.CTRL_MASK) != 0);
    if ((m & Event.ALT_MASK) != (pressedModifiers & Event.ALT_MASK))
      writeKeyEvent(Keysyms.Alt_L, (m & Event.ALT_MASK) != 0);
    if ((m & Event.META_MASK) != (pressedModifiers & Event.META_MASK))
      writeKeyEvent(Keysyms.Meta_L, (m & Event.META_MASK) != 0);
    pressedModifiers = m;
  }


  ////////////////////////////////////////////////////////////////////
  // The following methods are called from both RFB and GUI threads

  // the following are only ever accessed by the GUI thread:
  int buttonMask;
  int pressedModifiers;
}
